package com.example.sometestdemo.network

import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
import com.example.jsonktconverter.ktutils.JavaKotlinBridgeUtils
import okhttp3.ResponseBody
import retrofit2.Converter
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import kotlin.reflect.javaType

class FastJsonToDataBeanConverter<CT>(var clazz: Class<CT>, var mType: Type) :
    Converter<ResponseBody, CT> {
    lateinit var fastJson: JSONObject
    override fun convert(value: ResponseBody): CT? {
        val jsonText = value.toString()
        val kclazz = JavaKotlinBridgeUtils.getKClass(clazz)
        if (!kclazz.isData) {
            throw Exception("需要使用kotlin data类型")
        }
        fastJson = JSONObject.parseObject(jsonText)
        return jsonObjectConverterFun(clazz, fastJson, mType)
    }


    @OptIn(ExperimentalStdlibApi::class)
    fun <Q> jsonObjectConverterFun(clazzs: Class<Q>, textData: JSONObject, type: Type): Q {
        var genericCounter = 0
        var typeArray = arrayOf<Type>()
        if (wantConvertParameterizedType(type)) {
            typeArray = (type as ParameterizedType).actualTypeArguments
        }
        val kClazzCon = JavaKotlinBridgeUtils.getKClass(clazzs).constructors.first()
        val params = kClazzCon.parameters
        val includeParams = mutableListOf<Any>()
        for (index in params.indices) {
            val kclassk = params[index]
            val kclasskType = kclassk.type.toString()
            val classTemp = JavaKotlinBridgeUtils.getRawType(params[index].type.javaType)

            if (JavaKotlinBridgeUtils.getKClass(classTemp).isData) {
                includeParams.add(
                    jsonObjectConverterFun(
                        classTemp,
                        textData.getJSONObject(params[index].name),mType
                    )
                )
            } else if (!kclasskType.toString().contains(".")) {
                includeParams.add(
                    jsonObjectConverterFun(
                        JavaKotlinBridgeUtils.getRawType(typeArray[genericCounter]),
                        textData.getJSONObject(params[index].name),
                        typeArray[genericCounter]
                    )
                )
                genericCounter++
            } else if (classTemp.equals(List::class.java) || classTemp.equals(java.util.List::class.java)) {
                val listKclass =
                    JavaKotlinBridgeUtils.getRawType(params[index].type.arguments[0].type?.javaType)
                includeParams.add(
                    jsonArrayConverterFun(
                        listKclass,
                        textData.getJSONArray(params[index].name)
                    )
                )
            } else {
                includeParams.add(
                    textData.getObject(
                        params[index].name,
                        params[index].type.javaType
                    )
                )
            }
        }

        return kClazzCon.call(*includeParams.toTypedArray())
    }

    private fun <P> jsonArrayConverterFun(clazzs: Class<P>, textData: JSONArray): MutableList<P> {
        val listData = mutableListOf<P>()
        if (!JavaKotlinBridgeUtils.getKClass(clazzs).isData) {
            throw Exception("需要使用kotlin data类型")
        }
        for (index in textData.indices) {
            listData.add(jsonObjectConverterFun(clazzs, textData.getJSONObject(index),mType))
        }
        return listData
    }

    private fun wantConvertParameterizedType(wType: Type): Boolean =
        wType.toString().contains("<") && wType.toString().contains(">")
}
